#pragma once

#include <QMainWindow>
#include <QList>
#include <QLabel>
#include <QMenu>
#include <QAction>
#include <QString>
#include <QPainter>
#include <QMenuBar>
#include <QStatusBar>
#include <QDockWidget>
#include <QMouseEvent>
#include <QMessageBox>
#include <QFileDialog>
#include <QInputDialog>

#include <cmath>

#include "QNerveTissue.h"
#include "QNeuron.h"
#include "QReceptor.h"
#include "QTransmitter.h"
#include "QElectricSynapse.h"
#include "QInhibitorSynapse.h"
#include "QChemicalSynapse.h"

#include "src/QPlot.h"
#include "src/QPropertyWidget.h"
#include "src/QXmlModelHandler.h"

class QNeuronWindow: public QMainWindow
{
    Q_OBJECT
private:
    QList<QNerveTissue*> nerveList;
    int exNerveListLength;

    QPropertyWidget *propertyWidget;
    QDockWidget *propertyDock;

    QWidget *centralWidget;
    QLabel *statusLabel;

    QPlot *plot;
    QDockWidget *plotDock;
    int maxListCount;
    double *maxValue;

    int gridStep;
    bool hasBinding;

    QMenu *fileMenu;
    QMenu *modeMenu;
    QMenu *viewMenu;
    QMenu *helpMenu;

    QAction *newAction;
    QAction *loadAction;
    QAction *saveAction;
    QAction *stabilisationAction;
    QAction *startAction;
    QAction *stopAction;
    QAction *acceptAction;
    QAction *exitAction;

    QAction *freeAction;
    QAction *neuronAction;
    QAction *receptorAction;
    QAction *transmitterAction;
    QAction *electricSynapseAction;
    QAction *inhibitorSynapseAction;
    QAction *chemicalSynapseAction;

    QAction *showReceptorPotentialAction;
    QAction *showSynapseDirectionAction;
    QAction *showRelaxTimeAction;

    QAction *helpAction;
    QAction *aboutAction;
    QAction *aboutQtAction;

    int t;
    int mode;

    QPointF nodeStart;
    bool nodeDraw;
    QPointF nodeFinish;
    int moveNeuronCount;

    QString fileName;

    bool receptorPotentialVisible;
    bool synapseDirectionVisible;
    bool relaxTimeVisible;

    QString receptorPotentialStr;
    QString synapseDirectionStr;
    QString relaxTimeStr;

    int getNearestNeuron(QPointF point);

    void createActions(void);
    void createMenus(void);
    void createPlotWidget(void);
    void createPropertyWidget(void);
    void createStatusBar(void);

    void createNeuron(QPointF _pos);
    void createReceptor(QPointF _pos);
    void createTransmitter(QPointF _pos);
    void createElectricSynapse(QNerveTissue* sender, QNerveTissue* receiver);
    void createInhibitorSynapse(QNerveTissue* sender, QNerveTissue* receiver);
    void createChemicalSynapse(QNerveTissue* sender, QNerveTissue* receiver);

    void spreadImpulse(void);

public:
    QNeuronWindow(void);
    void setNerveList(QList<QNerveTissue*> nerveList);
    static QColor setColorByType(int type);
    static QDomElement xmlAddNerve(QDomDocument* xmlFile, QNerveTissue* node);

protected:
    void paintEvent(QPaintEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void closeEvent(QCloseEvent *event);

    void rebuildIDs(void);
    void updatePropertyWidget(void);
    void fillPropertyWidget(void);

public slots:
    void addCurve(int _id);
    void removeCurve(int _id);

    void setMode0(void);
    void setMode1(void);
    void setMode2(void);
    void setMode3(void);
    void setMode4(void);
    void setMode5(void);
    void setMode6(void);

    void emitImpulse(void);

    void setGridStep(int _gridStep);
    void setBinding(bool _hasBinding);

    void reset(void);
    void save(void);
    void load(void);
    void stabilisation(void);

    void acceptChanges(void);

    void showReceptorPotential(bool show);
    void showSynapseDirection(bool show);
    void showRelaxTime(bool show);

    void help(void);
    void about(void);

    void removeNerve(int _item);

signals:
    void nerveListChanged(QList<QNerveTissue*> _nerveList);
    void closeSignal(void);

};
